/*
 *	Features:
 *		Order Ascending and Descending by clicking the Col Headers
 *		Toolbar Popper
 *
 *	- DTD
 *		<!ELEMENT lexicon (rootWord+)>
 *		<!ELEMENT rootWord (englishWord+, filipinoWord+)>
 *		<!ATTLIST rootWord id ID #REQUIRED>
 *		<!ELEMENT englishWord (#PCDATA)>
 *		<!ELEMENT filipinoWord (#PCDATA)>
 *	- XML
 *		<lexicon>
 *			<rootWord id="root1"> -> unique
 *				<englishWord>thin</englishWord>
 *				<filipinoWord>payat</filipinoWord>
 *			</rootWord>
 *			<rootWord id="root2"> -> unique
 *				<englishWord>apple</englishWord>
 *				<filipinoWord>mansanas</filipinoWord>
 *			</rootWord>
 *		</lexicon>
 *
 *	- TODO: use only one DBConnector - all viewers!!!
 */

package text.ui;

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Hashtable;
import java.util.Vector;

import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JToolBar;
import javax.swing.JViewport;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableModel;

import text.util.DBConnector;

public class LexiconViewer extends Viewer {

	private JTable lexiconTable = null;
	private JButton buttonImport;
	private JButton buttonExport;

	public void setEnabled(boolean bEnabled) {
		if(buttonImport != null) {
			buttonImport.setEnabled(bEnabled);
		}
		
		if(buttonExport != null) {
			buttonExport.setEnabled(bEnabled);
		}
	}
	
    /**
     * main method allows us to run as a standalone demo.
     */
    public static void main(String[] args) {
		LexiconViewer lexiconViewer = new LexiconViewer(null);
		lexiconViewer.init();
    }
    
    /**
     * LexiconViewer Constructor
     */
    public LexiconViewer(GUI gui) {
        // Set the title for this demo, and an icon used to represent this
        // demo inside the GUI app.
        super(gui, "LexiconViewer", null);

		lexiconTable = createTable(createTableModel());
    }
    
	private TableModel createTableModel() {
//		Vector<String> vColumnNames = new Vector<String>();
		Vector vColumnNames = new Vector();
		vColumnNames.add("Lexicon #");
		vColumnNames.add("English Word");
		vColumnNames.add("Filipino Word");
//		Vector<Vector> vData = getLexiconData();
		Vector vData = getLexiconData();

		TableModel lexiconTableModel = new DefaultTableModel(vData, vColumnNames){
			public Class getColumnClass(int c) {
            	//hard coded: first col is an INTEGER for correct sorting of ID's
            	Class cClass = null;
            	
            	if(c == 0) {
            		try {
            			cClass = Class.forName("java.lang.Integer");
            		}catch(ClassNotFoundException e) {
            			e.printStackTrace();
            		}
            	}else {
            		cClass = getValueAt(0, c).getClass();
            	}
            	
            	return cClass;
            }
		};
		
		return lexiconTableModel;
	}

	private JTable createTable(TableModel tableModel) {
		
        TableSorter sorter = new TableSorter(tableModel);
        JTable table = new JTable(sorter){
/*		    public boolean isCellEditable(int row, int col) {
		    	return false;
		    }
*/		};
        sorter.setTableHeader(table.getTableHeader());

		table.getTableHeader().setReorderingAllowed(false);
		table.setDragEnabled(true);
		
		JScrollPane scroller = new JScrollPane();
		JViewport vp = scroller.getViewport();
		//scroller.setViewportView(table);

		JToolBar toolbarLexicon = new JToolBar();
		toolbarLexicon.setFloatable(false);

		buttonImport = toolbarLexicon.add(new ImportAction(this));
		buttonImport.setText("Import");
		
		buttonExport = toolbarLexicon.add(new ExportAction(this));
		buttonExport.setText("Export");

		vp.add(table);
        getViewerPanel().add(toolbarLexicon, BorderLayout.NORTH);
        getViewerPanel().add(scroller, BorderLayout.CENTER);
        
        return table;
	}

	private JTable getLexiconTable() {
		return lexiconTable;
	}

//	private Vector<Vector> getLexiconData() {
	private Vector getLexiconData() {
		
//		Vector<Vector> vRow = new Vector<Vector>();
		Vector vRow = new Vector();
		String	strQuery = "SELECT wordID, englishWord, filipinoWord FROM Lexicon ORDER BY wordID ASC";
			
		DBConnector.connect();
		ResultSet rsAll = DBConnector.select(strQuery);
		
		try{
			while(rsAll.next()) {
//				Vector<Object> vCol = new Vector<Object>();
				Vector vCol = new Vector();
				vCol.add(new Integer(rsAll.getInt("wordID")));
				vCol.add(rsAll.getString("englishWord"));
				vCol.add(rsAll.getString("filipinoWord"));
				vRow.add(vCol);
			}
		}catch(SQLException e){
			e.printStackTrace();
		}
		
		try {
			rsAll.close();
		} catch (SQLException e) {

			e.printStackTrace();
		}

		DBConnector.close();

		if(vRow.size() == 0) {
			vRow = null;
		}
	
		return vRow;
	}

	class ImportAction extends AbstractAction {
		LexiconViewer lexiconViewer;
	
		protected ImportAction(LexiconViewer lexiconViewer) {
			super("ImportAction");
			this.lexiconViewer = lexiconViewer;
		}

		public void actionPerformed(ActionEvent e) {
			int selectedIndex = JOptionPane.showConfirmDialog(null,
				"Are you sure you want to Import Lexicon?\n"+
				"This will automatically replace the contents of\n"+
				"the Lexicon DB with the contents of the XML file.",
				"XML Lexicon Import",
				JOptionPane.YES_NO_CANCEL_OPTION);
			
			if(selectedIndex == 0) {
				//select an xml file
				File xmlFile = openFile();
				Vector vXMLData = null;
				LexiconParser lexiconParser = new LexiconParser();
				
				if(xmlFile != null) {
					try {
						//parse the xml file
						lexiconParser.parseDoc(false, lexiconParser, xmlFile.getPath());
						vXMLData = lexiconParser.getData();

//						for (int i = 0; i < vXMLData.size(); i++) {
//							System.out.println(vXMLData.get(i));
//						}
					}catch (Exception ex) {
						ex.printStackTrace();
					}
					
					//store the words in the Vector of Hashtable containing Strings
					saveXMLToDB(vXMLData);

					//refresh
					if(lexiconViewer.getGUI() != null) {
						lexiconViewer.getGUI().refreshTable(lexiconViewer);
					}
				}else {
					//error!
				}
			}
		}

		private File openFile() {
			File f = null;
			JFileChooser fc = new JFileChooser();
			fc.setCurrentDirectory(new File("./resources/files/") );
			fc.setDialogTitle("Import XML");
			TExtFileFilter filter = new TExtFileFilter();
			filter.addExtension("xml");
			fc.setFileFilter(filter);
			int returnVal = fc.showOpenDialog(getViewerPanel());
			
			if (returnVal == JFileChooser.APPROVE_OPTION) {
				f = fc.getSelectedFile();
				if (!filter.accept(f)) {
					System.out.println("File not accepted.");
					f = null;
				}
	    	}
	    	
	    	return f;
		}

		private void saveXMLToDB(Vector vRow) {
			if(vRow != null && vRow.size() > 0) {
				boolean bCheck = false;
				
				DBConnector.connect();
				DBConnector.setAutoCommit(false);
		
				//delete the contents of the DB
				bCheck = DBConnector.update("DELETE FROM Lexicon");
		
				//insert everything from the vector to the DB
				for(int i=0; i < vRow.size() && bCheck; i++) {
					bCheck = DBConnector.update("INSERT INTO Lexicon "
						+ "(englishWord, filipinoWord) "
						+ "VALUES ('" + ((String)((Hashtable)vRow.get(i)).get("englishWord"+i)).replace("'","''") + "', '"
						+ ((String)((Hashtable)vRow.get(i)).get("filipinoWord"+i)).replace("'","''") + "')");
				}
		
				if(!bCheck)
					DBConnector.rollback();
				else
					DBConnector.commit();
		
				DBConnector.setAutoCommit(true);
				DBConnector.close();
			}
		}
	}

	class ExportAction extends AbstractAction {
		private LexiconViewer lexiconViewer;
		private	final String XML_DECLARATION = "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>";
		private	final String DTD_DECLARATION = "<!DOCTYPE lexicon SYSTEM \"lexicon.dtd\">";
		private	final String LINE_BREAK = "\r\n";
		private	final String TAB = "\t";
		private	final String OPEN_LEXICON_ELEM = "<lexicon>";
		private	final String CLOSE_LEXICON_ELEM = "</lexicon>";
		private	final String OPEN_ROOT_ELEM = "<rootWord id=\"root";
		private	final String CLOSE_ROOT_ELEM = "</rootWord>";
		private	final String OPEN_ENGLISH_ELEM = "<englishWord>";
		private	final String CLOSE_ENGLISH_ELEM = "</englishWord>";
		private	final String OPEN_FILIPINO_ELEM = "<filipinoWord>";
		private	final String CLOSE_FILIPINO_ELEM = "</filipinoWord>";
		
		protected ExportAction(LexiconViewer lexiconViewer) {
			super("ImportAction");
			this.lexiconViewer = lexiconViewer;
		}

		public void actionPerformed(ActionEvent e) {
			saveFile();
		}

		private void saveFile() {
			TExtFileFilter filter = new TExtFileFilter();
			filter.addExtension("xml");
			//create or choose a file
			JFileChooser fc = new JFileChooser();
			fc.setCurrentDirectory(new File("./resources/files/") );  
			fc.setDialogTitle("Export XML");
			fc.setFileFilter(filter);
			int returnVal = fc.showSaveDialog(getViewerPanel());
			
			if (returnVal == JFileChooser.APPROVE_OPTION) {
				File f = fc.getSelectedFile();
				if(f.exists()) {
					int selectedIndex = JOptionPane.showConfirmDialog(null, "The file, "+f.getName()+", already exists.\nDo you want to overwrite this file?", "Export XML", JOptionPane.YES_NO_OPTION);
					//YES
					if(selectedIndex == 0) {
						//get the contents of the DB
						Vector vDB = getDBContents();
						createFile(filter, f, vDB);
					}
				}else {
					//get the contents of the DB
					Vector vDB = getDBContents();
					createFile(filter, f, vDB);
				}
		  	}
		}
		
		private Vector getDBContents() {
			Vector vRow = new Vector();
			String	strQuery = "SELECT wordID, englishWord, filipinoWord FROM Lexicon ORDER BY wordID ASC";

			DBConnector.connect();
			ResultSet rsAll = DBConnector.select(strQuery);

			try{
				while(rsAll.next()) {
					Vector vCol = new Vector();
//					vCol.add(rsAll.getString("wordID"));
					vCol.add(new Integer(rsAll.getInt("wordID")));
					vCol.add(rsAll.getString("englishWord"));
					vCol.add(rsAll.getString("filipinoWord"));
					vRow.add(vCol);
				}
			}catch(SQLException e){
				e.printStackTrace();
			}

			DBConnector.close();

			if(vRow.size() == 0) {
				vRow = null;
			}

			return vRow;
		}
		
		private void createFile(TExtFileFilter filter, File f, Vector vDB) {
			//check if DB is empty
			//YES: warn the user that DB is empty so no XML file will be created
			if(vDB == null) {
				JOptionPane.showMessageDialog(null, "The Lexicon Database does not contain any data therefore no XML file will be created.", "Export XML", JOptionPane.WARNING_MESSAGE);
			}
			//NO: create XML file
			else {
				StringBuffer sbFileContents = new StringBuffer();
	
				//create the xml file
				sbFileContents.append((XML_DECLARATION + LINE_BREAK + DTD_DECLARATION + LINE_BREAK));
				sbFileContents.append((OPEN_LEXICON_ELEM + LINE_BREAK));
				for(int i = 0; i < vDB.size(); i++) {
					sbFileContents.append((TAB + OPEN_ROOT_ELEM + ((Vector)vDB.get(i)).get(0) +"\">" + LINE_BREAK));
					sbFileContents.append((TAB + TAB + OPEN_ENGLISH_ELEM + ((Vector)vDB.get(i)).get(1) + CLOSE_ENGLISH_ELEM + LINE_BREAK));
					sbFileContents.append((TAB + TAB + OPEN_FILIPINO_ELEM + ((Vector)vDB.get(i)).get(2) + CLOSE_FILIPINO_ELEM + LINE_BREAK));
					sbFileContents.append((TAB + CLOSE_ROOT_ELEM + LINE_BREAK));
				}
				sbFileContents.append(CLOSE_LEXICON_ELEM);
				sbFileContents.trimToSize();

				if(!filter.accept(f)) {
					f = filter.appendExtension(f, ".xml");
				}
				if (filter.accept(f)) {
					try{
			            FileWriter fw = new FileWriter(f);
			            fw.write(sbFileContents.toString());
			            fw.close();
					}catch(FileNotFoundException fnfe) {
					}catch(IOException ioe) {
					}catch(Exception ex) {
					}
				}else{
					System.out.println("File not accepted.");
				}
			}
		}
	}
}